import cv2
import matplotlib.pyplot as plt
import numpy as np

img = cv2.imread("../images/lena.png")
h, w, _ = img.shape

# 1. 转为灰度图  变成二维数组
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 2. 对灰度图绘制直方图
# 2.1 使用matplotlib进行绘制
plt.hist(img_gray.flatten(),    # 记得展平一下
         bins=256,              # 分箱数
         range=(0, 256),        # 坐标轴显示的区间范围
         density=True           # 进行归一化
         )


# 2.2 使用OpenCV绘制直方图
# 2.2.1 先计算直方图——统计灰度图中每个像素值的 像素点的个数
hist = cv2.calcHist(
    [img_gray],     # 注意图像要放在列表中
    [0],           # 通道数，单通道是[0] 三通道分别是[0] [1] [2]
    None,            # 掩码
    [256],          # 分箱数 类似于plt中bins
    (0, 256)        # 通道像素值的取值范围0到255
)
# 返回值是一个NumPy数组
print(hist.shape)   # (256, 1)
#返回的是灰度值的数量
print(hist)
# 2.2.2 根据统计到的直方图，进行图形绘制
hist_img = np.zeros((256, 256, 3), dtype="u1")
# 可以确定的是宽度（像素值的取值范围）256，但是高度可不是256，因为高度表示统计到的像素点的个数，
# 刚才看到统计到有 [8.660e+02]、[1.036e+03]等，所以我们需要手动进行归一化
# 归一化 = 每一个值 / 最大值    最大值就是1  其余就是[0, 1]
# 但是咱们要清楚一点：1px肉眼识别不太到，所以我们还需要将归一化[0, 1] * 256 = [0, 256] * 0.9
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(hist)
for i in range(256):
    ret = int(hist[i][0] / max_val * 256 * 0.9)
    cv2.line(
        hist_img,
        # 注意区分 图像的h轴(y轴) 和实际的数学坐标系是相反的
        (i, 256),
        (i, 256-ret),
        (0,0,255)
    )
cv2.imshow('hist_img', hist_img)
plt.show()
cv2.waitKey(0)